package com.example.ShoppingManagementSystem.service;

import com.example.ShoppingManagementSystem.entity.CartItem;
import com.example.ShoppingManagementSystem.entity.Customer;
import com.example.ShoppingManagementSystem.entity.Product;
import com.example.ShoppingManagementSystem.entity.PurchaseHistory;
import com.example.ShoppingManagementSystem.repository.CartItemRepository;
import com.example.ShoppingManagementSystem.repository.CustomerRepository;
import com.example.ShoppingManagementSystem.repository.ProductRepository;
import com.example.ShoppingManagementSystem.repository.PurchaseHistoryRepository;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.SecureRandom;
import java.sql.Date;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

@Service
public class CustomerServicempl implements CustomerService {

    private final CustomerRepository customerRepository;



    private final CartItemRepository cartItemRepository;

    private final PurchaseHistoryRepository purchaseHistoryRepository;

    private final JavaMailSender mailSender;

    private final ProductRepository productRepository;

    public CustomerServicempl(CustomerRepository customerRepository, CartItemRepository cartItemRepository, PurchaseHistoryRepository purchaseHistoryRepository, JavaMailSender mailSender, ProductRepository productRepository) {
        this.customerRepository = customerRepository;

        this.cartItemRepository = cartItemRepository;
        this.purchaseHistoryRepository = purchaseHistoryRepository;
        this.mailSender = mailSender;
        this.productRepository = productRepository;
    }


    @Override
    public Customer loginCustomer(String username, String password) {
        Customer user = customerRepository.findByUsername(username);
        if (user != null && password.equals(user.getPassword())) {
            return user;
        }
        return null;
    }

    @Override
    public Customer registerCustomer(String username, String password, String PhoneNumber, String email) {
        System.out.println("1");
        if (isValidPassword(password)) {
            throw new RuntimeException("Password does not meet complexity requirements.");
        }
        System.out.println("2");
        if (customerRepository.findByUsername(username)!=null) {
            throw new RuntimeException("User already exists.");
        }
        System.out.println("3");
        if (username.length()<5) {
            throw new RuntimeException("The username must have at least 5 characters.");
        }
        System.out.println("4");
        Customer newCustomer = new Customer(username,password,PhoneNumber,email);
        System.out.println("date");
        ///后面你自己在加密
        System.out.println("5");
        newCustomer.setUserLevel("铜牌客户");
        System.out.println("6");
        return customerRepository.save(newCustomer);
    }

    @Override
    public void updatePassword(int customerId, String newPassword) {
        if (isValidPassword(newPassword)) {
            throw new RuntimeException("newPassword does not meet complexity requirements.");
        }
        if (customerRepository.findById(customerId).isEmpty()) {
            throw new RuntimeException("User does not exists.");
        }
        Customer customer=customerRepository.getReferenceById(customerId);
//        customer.setPassword(passwordEncoder.encode(newPassword));
        customerRepository.save(customer);
    }

    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+[]{}|;:',.<>?/";
    private static final int PASSWORD_LENGTH = 12; // Example length
    private static final Pattern PASSWORD_PATTERN = Pattern.compile(
            "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[\\W_]).{9,}$\n"
    );

    @Override
    public boolean resetPassword(String username, String email) {
        Optional<Customer> customerOpt = Optional.ofNullable(customerRepository.findByUsername(username));
        if (customerOpt.isPresent() && customerOpt.get().getEmail().equals(email)) {
            String newPassword = generateRandomPassword();
            if (isValidPassword(newPassword)) {
                customerOpt.get().setPassword(newPassword);
                customerRepository.save(customerOpt.get());
                sendPasswordEmail(email, newPassword);
                return true;
            }
        }
        return false;
    }


    @Override
    public void addToCart(int customerId, int productId, int quantity) {
        CartItem item = new CartItem(customerId,productId,quantity);
        cartItemRepository.save(item);
    }

    @Transactional
    @Override
    public void removeFromCart(int customerId, int productId) {
        cartItemRepository.deleteByCustomerIdAndProductId(customerId,productId);
    }

    @Override
    public void updateCartItemQuantity(int customerId,int productId, int newQuantity) {
        CartItem item = cartItemRepository.findByCustomerIdAndProductId(customerId,productId);
        if (newQuantity <= 0) {
            cartItemRepository.delete(item);
        } else {
            item.setQuantity(newQuantity);
            cartItemRepository.save(item);
        }
    }

    @Override
    public List<PurchaseHistory> getAllPurchaseHistory(int customerId) {
        return purchaseHistoryRepository.findAllByUserID(customerId);
    }

    @Override
    public void pay(int customerId, int productId, int quantity) {
            if (customerRepository.findById(customerId).isEmpty()) {
                throw new RuntimeException("User does not exist.");
            }
            Optional<Product> productOptional = productRepository.findById(productId);
            if (productOptional.isEmpty()) {
                throw new RuntimeException("Product does not exist.");
            }
            Product product = productOptional.get();
            CartItem item = cartItemRepository.findByCustomerIdAndProductId(customerId, productId);
            if (item == null) {
                throw new RuntimeException("Cart item does not exist.");
            }
            PurchaseHistory purchaseHistory = new PurchaseHistory();
            purchaseHistory.setProductID(productId);
            purchaseHistory.setUserID(customerId);
            purchaseHistory.setPurchaseDate(new Date(System.currentTimeMillis()));
            int availableQuantity = item.getQuantity();
            if (availableQuantity < quantity) {
                purchaseHistory.setQuantity(availableQuantity);
                purchaseHistory.setTotalPrice(availableQuantity * product.getRetailPrice());
                cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId);
            } else {
                purchaseHistory.setQuantity(quantity);
                purchaseHistory.setTotalPrice(quantity * product.getRetailPrice());
                if (availableQuantity > quantity) {
                    item.setQuantity(availableQuantity - quantity);
                    cartItemRepository.save(item);
                } else {
                    cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId);
                }
            }
            purchaseHistoryRepository.save(purchaseHistory);
    }

    @Override
    public List<CartItem> checkout(int customerId) {
        return cartItemRepository.findAllByCustomerId(customerId);
    }




    private boolean isValidPassword(String password) {
        return PASSWORD_PATTERN.matcher(password).matches();
    }

    private void sendPasswordEmail(String to, String newPassword) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject("Password Reset");
        message.setText("Your new password is: " + newPassword);
        mailSender.send(message);

    }

    private String generateRandomPassword(){
        SecureRandom random = new SecureRandom();
        StringBuilder sb = new StringBuilder(PASSWORD_LENGTH);
        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
        }
        return sb.toString();
    }

}
